home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Programming / Wipeout / source / main.c < prev    next >
C/C++ Source or Header  |  2001-02-06  |  19KB  |  857 lines

  1. /*
  2.  * $Id: main.c 1.21 2000/12/18 16:23:37 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * Wipeout -- Traces and munges memory and detects memory trashing
  7.  *
  8.  * Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  9.  * Public Domain
  10.  */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "global.h"
  14. #endif    /* _GLOBAL_H */
  15.  
  16. /******************************************************************************/
  17.  
  18. #include "Wipeout_rev.h"
  19.  
  20. /******************************************************************************/
  21.  
  22. const STRPTR VersTag = VERSTAG;
  23.  
  24. /******************************************************************************/
  25.  
  26. STATIC const STRPTR Separator = "======================================="
  27.                                 "=======================================";
  28.  
  29. /******************************************************************************/
  30.  
  31. STATIC struct WipeoutSemaphore *    WipeoutSemaphore;
  32. STATIC BOOL                            WipeoutSemaphoreCreated;
  33.  
  34. /******************************************************************************/
  35.  
  36. STATIC BOOL ShowBannerMessage = TRUE;
  37.  
  38. /******************************************************************************/
  39.  
  40. STATIC BYTE TimerSignal;
  41.  
  42. /******************************************************************************/
  43.  
  44. STATIC LONG ASM
  45. ControlFunc(REG(a0) struct TagItem *tags)
  46. {
  47.     struct TagItem * list = tags;
  48.     struct TagItem * ti;
  49.     struct TrackHeader * th;
  50.     APTR address = NULL;
  51.     LONG result = 0;
  52.  
  53.     Forbid();
  54.  
  55.     while((ti = NextTagItem(&list)) != NULL)
  56.     {
  57.         switch(ti->ti_Tag)
  58.         {
  59.             case WOT_Address:
  60.  
  61.                 address = (APTR)ti->ti_Data;
  62.                 break;
  63.  
  64.             case WOT_SetPC:
  65.  
  66.                 if(IsTrackedAllocation((ULONG)address,&th) ||
  67.                    IsTrackedAllocation((ULONG)(address)-sizeof(LONG),&th))
  68.                 {
  69.                     th->th_PC = ti->ti_Data;
  70.                     th->th_ShowPC = TRUE;
  71.                     FixTrackHeaderChecksum(th);
  72.                 }
  73.  
  74.                 break;
  75.         }
  76.     }
  77.  
  78.     Permit();
  79.  
  80.     return(result);
  81. }
  82.  
  83. /******************************************************************************/
  84.  
  85. STATIC struct WipeoutSemaphore *
  86. FindWipeoutSemaphore(VOID)
  87. {
  88.     struct WipeoutSemaphore * ws;
  89.  
  90.     ws = (struct WipeoutSemaphore *)FindSemaphore(WIPEOUTSEMAPHORENAME);
  91.  
  92.     return(ws);
  93. }
  94.  
  95. STATIC VOID
  96. DeleteWipeoutSemaphore(struct WipeoutSemaphore * ws)
  97. {
  98.     if(ws != NULL)
  99.     {
  100.         /* remove the semaphore from the public list */
  101.         RemSemaphore((struct SignalSemaphore *)ws);
  102.  
  103.         /* gain ownership over it */
  104.         ObtainSemaphore((struct SignalSemaphore *)ws);
  105.         ReleaseSemaphore((struct SignalSemaphore *)ws);
  106.  
  107.         /* and release it */
  108.         FreeMem(ws,sizeof(*ws));
  109.     }
  110. }
  111.  
  112. STATIC struct WipeoutSemaphore *
  113. CreateWipeoutSemaphore(VOID)
  114. {
  115.     struct WipeoutSemaphore * ws;
  116.  
  117.     ws = AllocMem(sizeof(*ws),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  118.     if(ws != NULL)
  119.     {
  120.         /* fill in name and priority; AddSemaphore() will take
  121.          * care of the rest
  122.           */
  123.         ws->ws_SignalSemaphore.ss_Link.ln_Name    = ws->ws_SemaphoreName;
  124.         ws->ws_SignalSemaphore.ss_Link.ln_Pri    = 1;
  125.  
  126.         strcpy(ws->ws_SemaphoreName,WIPEOUTSEMAPHORENAME);
  127.  
  128.         /* for compatibility checking, if the semaphore
  129.          * needs to grow
  130.          */
  131.         ws->ws_Version            = WIPEOUTSEMAPHOREVERSION;
  132.         ws->ws_Revision            = WIPEOUTSEMAPHOREREVISION;
  133.  
  134.         /* fill in references to changeable parameters */
  135.         ws->ws_IsActive            = &IsActive;
  136.         ws->ws_ShowFail            = &ShowFail;
  137.         ws->ws_WaitAfterHit        = &WaitAfterHit;
  138.         ws->ws_NameTag            = &NameTag;
  139.         ws->ws_NameTag            = &NameTag;
  140.         ws->ws_CheckConsistency    = &CheckConsistency;
  141.         ws->ws_ARegCheck        = &ARegCheck;
  142.         ws->ws_DRegCheck        = &DRegCheck;
  143.         ws->ws_StackCheck        = &StackCheck;
  144.         ws->ws_StackLines        = &StackLines;
  145.         ws->ws_CheckDelay        = &CheckDelay;
  146.         ws->ws_WipeoutTask        = FindTask(NULL);
  147.         ws->ws_WakeupMask        = (1UL << WakeupSignal);
  148.  
  149.         ws->ws_ControlFunc        = (WipeoutControlFunc)ControlFunc;
  150.  
  151.         /* and finally make the semaphore public */
  152.         AddSemaphore((struct SignalSemaphore *)ws);
  153.     }
  154.  
  155.     return(ws);
  156. }
  157.  
  158. /******************************************************************************/
  159.  
  160. STATIC LONG
  161. SendWipeoutCmd(LONG command,APTR parameter)
  162. {
  163.     WipeoutSemaphore->ws_Client        = FindTask(NULL);
  164.     WipeoutSemaphore->ws_Command    = command;
  165.     WipeoutSemaphore->ws_Parameter    = parameter;
  166.     WipeoutSemaphore->ws_Error        = OK;
  167.  
  168.     /* wake up the wipeout semaphore owner and exchange
  169.      * data or information with it
  170.      */
  171.     SetSignal(0,SIG_Handshake);
  172.     Signal(WipeoutSemaphore->ws_WipeoutTask,WipeoutSemaphore->ws_WakeupMask);
  173.     Wait(SIG_Handshake);
  174.  
  175.     return(WipeoutSemaphore->ws_Error);
  176. }
  177.  
  178. /******************************************************************************/
  179.  
  180. STATIC VOID
  181. Cleanup(VOID)
  182. {
  183.     /* shut down the timer */
  184.     DeleteTimer();
  185.  
  186.     /* dispose of the semaphore */
  187.     if(WipeoutSemaphoreCreated)
  188.     {
  189.         DeleteWipeoutSemaphore(WipeoutSemaphore);
  190.         WipeoutSemaphore = NULL;
  191.     }
  192.  
  193.     /* release the semaphore */
  194.     if(WipeoutSemaphore != NULL)
  195.     {
  196.         ReleaseSemaphore((struct SignalSemaphore *)WipeoutSemaphore);
  197.         WipeoutSemaphore = NULL;
  198.     }
  199.  
  200.     /* clear the allocation filters */
  201.     ClearFilterList();
  202.  
  203.     /* get rid of the wakeup signal */
  204.     if(WakeupSignal != -1)
  205.     {
  206.         FreeSignal(WakeupSignal);
  207.         WakeupSignal = -1;
  208.     }
  209.  
  210.     /* close utility.library, if this is necessary */
  211.     #if !defined(__SASC) || defined(_M68020)
  212.     {
  213.         if(UtilityBase != NULL)
  214.         {
  215.             CloseLibrary(UtilityBase);
  216.             UtilityBase = NULL;
  217.         }
  218.     }
  219.     #endif
  220. }
  221.  
  222. STATIC BOOL
  223. Setup(VOID)
  224. {
  225.     LONG error = OK;
  226.     int i;
  227.  
  228.     WakeupSignal = -1;
  229.     InitFilterList();
  230.  
  231.     /* Kickstart 2.04 or higher required */
  232.     if(SysBase->LibNode.lib_Version < 37)
  233.     {
  234.         const STRPTR message = "This program requires Kickstart 2.04 or better.\n";
  235.  
  236.         Write(Output(),message,strlen(message));
  237.         return(FAILURE);
  238.     }
  239.  
  240.     /* determine the program name */
  241.     StrcpyN(sizeof(ProgramName),ProgramName,VERS);
  242.  
  243.     for(i = strlen(ProgramName) - 1 ; i >= 0 ; i--)
  244.     {
  245.         if(ProgramName[i] == ' ')
  246.         {
  247.             ProgramName[i] = '\0';
  248.             break;
  249.         }
  250.     }
  251.  
  252.     /* open utility.library, if this is necessary */
  253.     #if !defined(__SASC) || defined(_M68020)
  254.     {
  255.         UtilityBase = OpenLibrary("utility.library",37);
  256.         if(UtilityBase == NULL)
  257.         {
  258.             Printf("%s: Could not open utility.library V37.\n",ProgramName);
  259.             return(FAILURE);
  260.         }
  261.     }
  262.     #endif
  263.  
  264.     /* allocate the timer data */
  265.     TimerSignal = CreateTimer();
  266.     if(TimerSignal == -1)
  267.     {
  268.         Printf("%s: Could not create timer.\n",ProgramName);
  269.         return(FAILURE);
  270.     }
  271.  
  272.     /* allocate the wakeup signal */
  273.     WakeupSignal = AllocSignal(-1);
  274.     if(WakeupSignal == -1)
  275.     {
  276.         Printf("%s: Could not allocate wakeup signal.\n",ProgramName);
  277.         return(FAILURE);
  278.     }
  279.  
  280.     /* establish default options */
  281.     PreWallSize        = 32;
  282.     PostWallSize    = 32;
  283.     IsActive        = TRUE;
  284.     StackLines        = 2;
  285.  
  286.     Forbid();
  287.  
  288.     /* try to find the global wipeout semaphore */
  289.     WipeoutSemaphore = FindWipeoutSemaphore();
  290.     if(WipeoutSemaphore == NULL)
  291.     {
  292.         /* it does not exist yet; create it */
  293.         WipeoutSemaphore = CreateWipeoutSemaphore();
  294.         if(WipeoutSemaphore != NULL)
  295.         {
  296.             WipeoutSemaphoreCreated = TRUE;
  297.         }
  298.         else
  299.         {
  300.             error = ERROR_NO_FREE_STORE;
  301.         }
  302.     }
  303.     else if (WipeoutSemaphore->ws_Version != WIPEOUTSEMAPHOREVERSION)
  304.     {
  305.         error = ERROR_OBJECT_WRONG_TYPE;
  306.     }
  307.     else
  308.     {
  309.         /* obtain ownership of the semaphore */
  310.         ObtainSemaphore((struct SignalSemaphore *)WipeoutSemaphore);
  311.     }
  312.  
  313.     Permit();
  314.  
  315.     if(error == OK)
  316.     {
  317.         struct RDArgs * rda;
  318.  
  319.         /* these are the command line parameters, later
  320.          * filled in by ReadArgs() below
  321.          */
  322.         struct
  323.         {
  324.             /* the following options control the startup defaults
  325.              * and cannot be changed by subsequent invocations
  326.              * of Wipeout
  327.              */
  328.             NUMBER    PreSize;
  329.             NUMBER    PostSize;
  330.             KEY        FillChar;
  331.             SWITCH    Parallel;
  332.             SWITCH    NoBanner;
  333.  
  334.             /* the following options can be changed at run-time */
  335.             SWITCH    Remunge;
  336.             SWITCH    Check;
  337.             SWITCH    Mark;
  338.             SWITCH    Unmark;
  339.             SWITCH    ShowUnmarked;
  340.             KEY        Name;
  341.             SWITCH    NameTag;
  342.             SWITCH    NoNameTag;
  343.             SWITCH    Active;
  344.             SWITCH    Inactive;
  345.             SWITCH    Wait;
  346.             SWITCH    NoWait;
  347.             SWITCH    ConsistenceCheck;
  348.             SWITCH    NoConsistenceCheck;
  349.             SWITCH    Reuse;
  350.             SWITCH    NoReuse;
  351.             SWITCH    ShowFail;
  352.             SWITCH    NoShowFail;
  353.             SWITCH    ARegCheck;
  354.             SWITCH    NoARegCheck;
  355.             SWITCH    DRegCheck;
  356.             SWITCH    NoDRegCheck;
  357.             SWITCH    StackCheck;
  358.             SWITCH    NoStackCheck;
  359.             NUMBER    StackLines;
  360.             NUMBER    CheckDelay;
  361.         } params;
  362.     
  363.         /* this is the command template, as required by ReadArgs() below;
  364.          * its contents must match the "params" data structure above
  365.          */
  366.         const STRPTR cmdTemplate =
  367.             "PRESIZE/K/N,"
  368.             "POSTSIZE/K/N,"
  369.             "FILLCHAR/K,"
  370.             "PARALLEL/S,"
  371.             "QUIET=NOBANNER/S,"
  372.             "REMUNGE=REMUNG/S,"
  373.             "CHECK/S,"
  374.             "MARK/S,"
  375.             "UNMARK/S,"
  376.             "SHOWUNMARKED/S,"
  377.             "NAME=TASK/K,"
  378.             "NAMETAG/S,"
  379.             "NONAMETAG/S,"
  380.             "ACTIVE=ENABLE/S,"
  381.             "INACTIVE=DISABLE/S,"
  382.             "WAIT/S,"
  383.             "NOWAIT/S,"
  384.             "CONSISTENCECHECK/S,"
  385.             "NOCONSISTENCECHECK/S,"
  386.             "REUSE/S,"
  387.             "NOREUSE/S,"
  388.             "SHOWFAIL/S,"
  389.             "NOSHOWFAIL/S,"
  390.             "AREGCHECK/S,"
  391.             "NOAREGCHECK/S,"
  392.             "DREGCHECK/S,"
  393.             "NODREGCHECK/S,"
  394.             "STACKCHECK/S,"
  395.             "NOSTACKCHECK/S,"
  396.             "STACKLINES/K/N,"
  397.             "CHECKDELAY/K/N";
  398.  
  399.         memset(¶ms,0,sizeof(params));
  400.  
  401.         /* read the command line parameters */
  402.         rda = ReadArgs((STRPTR)cmdTemplate,(LONG *)¶ms,NULL);
  403.         if(rda != NULL)
  404.         {
  405.             struct WipeoutSemaphore * ws = WipeoutSemaphore;
  406.  
  407.             /* set the pre-wall allocation size */
  408.             if(params.PreSize != NULL)
  409.             {
  410.                 LONG value;
  411.  
  412.                 value = (*params.PreSize);
  413.                 if(value < MEM_BLOCKSIZE)
  414.                     value = MEM_BLOCKSIZE;
  415.                 else if (value > 65536)
  416.                     value = 65536;
  417.  
  418.                 PreWallSize = (value + MEM_BLOCKMASK) & ~MEM_BLOCKMASK;
  419.             }
  420.  
  421.             /* set the post-wall allocation size */
  422.             if(params.PostSize != NULL)
  423.             {
  424.                 LONG value;
  425.  
  426.                 value = (*params.PostSize);
  427.                 if(value < MEM_BLOCKSIZE)
  428.                     value = MEM_BLOCKSIZE;
  429.                 else if (value > 65536)
  430.                     value = 65536;
  431.  
  432.                 PostWallSize = (value + MEM_BLOCKMASK) & ~MEM_BLOCKMASK;
  433.             }
  434.  
  435.             /* use a special fill character? */
  436.             if(params.FillChar != NULL)
  437.             {
  438.                 LONG number;
  439.  
  440.                 /* this can either be a decimal or a
  441.                  * hexadecimal number; the latter is
  442.                  * indicated by a preceding "$" or "0x"
  443.                  */
  444.                 if(DecodeNumber(params.FillChar,&number))
  445.                 {
  446.                     if(0 <= number && number <= 255)
  447.                         SetFillChar(number);
  448.                     else
  449.                         error = ERROR_BAD_NUMBER;
  450.                 }
  451.                 else
  452.                 {
  453.                     error = ERROR_BAD_NUMBER;
  454.                 }
  455.             }
  456.  
  457.             /* enable parallel port output? */
  458.             if(params.Parallel)
  459.                 ChooseParallelOutput();
  460.  
  461.             /* do not show the banner message? */
  462.             if(params.NoBanner)
  463.                 ShowBannerMessage = FALSE;
  464.  
  465.             /* remunge memory? */
  466.             if(params.Remunge)
  467.             {
  468.                 /* tell the semaphore owner to munge the memory */
  469.                 if(NO WipeoutSemaphoreCreated)
  470.                     SendWipeoutCmd(WIPEOUTCMD_Remunge,NULL);
  471.             }
  472.  
  473.             /* trigger a memory check? */
  474.             if(params.Check)
  475.                 Signal(ws->ws_WipeoutTask,SIG_Check);
  476.  
  477.             /* mark all allocations? */
  478.             if(params.Mark)
  479.             {
  480.                 /* tell the semaphore owner to mark the allocations */
  481.                 if(NO WipeoutSemaphoreCreated)
  482.                     SendWipeoutCmd(WIPEOUTCMD_Mark,NULL);
  483.             }
  484.  
  485.             /* clear all allocation marks? */
  486.             if(params.Unmark)
  487.             {
  488.                 /* tell the semaphore owner to clear the marks */
  489.                 if(NO WipeoutSemaphoreCreated)
  490.                     SendWipeoutCmd(WIPEOUTCMD_Unmark,NULL);
  491.             }
  492.  
  493.             /* show all unmarked allocations? */
  494.             if(params.ShowUnmarked)
  495.             {
  496.                 /* tell the semaphore owner to clear the marks */
  497.                 if(NO WipeoutSemaphoreCreated)
  498.                     SendWipeoutCmd(WIPEOUTCMD_ShowUnmarked,NULL);
  499.             }
  500.  
  501.             /* put together a list of tasks to filter out
  502.              * when making memory allocations?
  503.              */
  504.             if(params.Name != NULL)
  505.             {
  506.                 if(WipeoutSemaphoreCreated)
  507.                 {
  508.                     /* we created the semaphore, so we can
  509.                      * fill in the filter lists all by
  510.                      * ourselves.
  511.                      */
  512.                     if(CANNOT UpdateFilter(params.Name))
  513.                         error = ERROR_NO_FREE_STORE;
  514.                 }
  515.                 else
  516.                 {
  517.                     /* we did not create the semaphore,
  518.                      * so we will have to tell the semaphore
  519.                      * owner to update the filter lists.
  520.                      */
  521.                     error = SendWipeoutCmd(WIPEOUTCMD_UpdateFilterList,params.Name);
  522.                 }
  523.             }
  524.  
  525.             if(params.NameTag)
  526.                 (*ws->ws_NameTag) = TRUE;
  527.  
  528.             if(params.NoNameTag)
  529.                 (*ws->ws_NameTag) = FALSE;
  530.  
  531.             /* enable wipeout? */
  532.             if(params.Active)
  533.                 Signal(ws->ws_WipeoutTask,SIG_Enable);
  534.  
  535.             /* disable wipeout? */
  536.             if(params.Inactive)
  537.                 Signal(ws->ws_WipeoutTask,SIG_Disable);
  538.  
  539.             if(params.Wait)
  540.                 (*ws->ws_WaitAfterHit) = TRUE;
  541.  
  542.             if(params.NoWait)
  543.                 (*ws->ws_WaitAfterHit) = FALSE;
  544.  
  545.             if(params.ConsistenceCheck)
  546.                 (*ws->ws_CheckConsistency) = TRUE;
  547.  
  548.             if(params.NoConsistenceCheck)
  549.                 (*ws->ws_CheckConsistency) = FALSE;
  550.  
  551.             if(params.Reuse)
  552.                 (*ws->ws_NoReuse) = FALSE;
  553.  
  554.             if(params.NoReuse)
  555.                 (*ws->ws_NoReuse) = TRUE;
  556.  
  557.             if(params.ShowFail)
  558.                 (*ws->ws_ShowFail) = TRUE;
  559.  
  560.             if(params.NoShowFail)
  561.                 (*ws->ws_ShowFail) = FALSE;
  562.  
  563.             if(params.ARegCheck)
  564.                 (*ws->ws_ARegCheck) = TRUE;
  565.  
  566.             if(params.NoARegCheck)
  567.                 (*ws->ws_ARegCheck) = FALSE;
  568.  
  569.             if(params.DRegCheck)
  570.                 (*ws->ws_DRegCheck) = TRUE;
  571.  
  572.             if(params.NoDRegCheck)
  573.                 (*ws->ws_DRegCheck) = FALSE;
  574.  
  575.             if(params.StackCheck)
  576.                 (*ws->ws_StackCheck) = TRUE;
  577.  
  578.             if(params.NoStackCheck)
  579.                 (*ws->ws_StackCheck) = FALSE;
  580.  
  581.             if(params.StackLines != NULL)
  582.             {
  583.                 LONG value;
  584.  
  585.                 value = (*params.StackLines);
  586.                 if(value < 0)
  587.                     value = 0;
  588.  
  589.                 (*ws->ws_StackLines) = value;
  590.             }
  591.  
  592.             /* set or update the automatic check delay? */
  593.             if(params.CheckDelay != NULL)
  594.             {
  595.                 LONG value;
  596.  
  597.                 value = (*params.CheckDelay);
  598.                 if(value < 0)
  599.                     value = 0;
  600.  
  601.                 CheckDelay = value;
  602.  
  603.                 /* notify the semaphore owner of the
  604.                  * new check delay; this will automatically
  605.                  * trigger a new memory check
  606.                  */
  607.                 if(NO WipeoutSemaphoreCreated)
  608.                     error = SendWipeoutCmd(WIPEOUTCMD_NewCheckDelay,(APTR)CheckDelay);
  609.             }
  610.  
  611.             FreeArgs(rda);
  612.         }
  613.         else
  614.         {
  615.             error = IoErr();
  616.         }
  617.     }
  618.  
  619.     if(error == OK)
  620.     {
  621.         /* set up the tracking lists */
  622.         SetupAllocationList();
  623.         SetupPoolList();
  624.  
  625.         return(SUCCESS);
  626.     }
  627.     else
  628.     {
  629.         if(error == ERROR_OBJECT_WRONG_TYPE)
  630.             Printf("%s: Global semaphore version mismatch; please reinstall 'Wipeout' and reboot.\n",ProgramName);
  631.         else
  632.             PrintFault(error,ProgramName);
  633.  
  634.         return(FAILURE);
  635.     }
  636. }
  637.  
  638. /******************************************************************************/
  639.  
  640. int
  641. main(
  642.     int        argc,
  643.     char **    argv)
  644. {
  645.     int result = RETURN_FAIL;
  646.  
  647.     /* set up all the data we need */
  648.     if(Setup())
  649.     {
  650.         result = RETURN_OK;
  651.  
  652.         /* are we the owner of the semaphore? if
  653.          * so, do something useful
  654.          */
  655.         if(WipeoutSemaphoreCreated)
  656.         {
  657.             ULONG signalsReceived;
  658.             ULONG sigWakeup = (1UL<<WakeupSignal);
  659.             ULONG sigTimer = (1UL<<TimerSignal);
  660.     
  661.             /* munge all free memory */
  662.             if(ShowBannerMessage)
  663.             {
  664.                 DPrintf("%s -- Traces and munges memory and detects memory trashing\n",ProgramName);
  665.                 DPrintf("Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>\n");
  666.                 DPrintf("Public Domain\n\n");
  667.  
  668.                 DPrintf("Munging memory... ");
  669.             }
  670.  
  671.             BeginMemMung();
  672.  
  673.             if(ShowBannerMessage)
  674.             {
  675.                 struct timeval tv;
  676.  
  677.                 Forbid();
  678.                 GetSysTime(&tv);
  679.                 ConvertTimeAndDate(&tv,GlobalDateTimeBuffer);
  680.                 DPrintf("done (%s).\n",GlobalDateTimeBuffer);
  681.                 Permit();
  682.             }
  683.     
  684.             /* plant the monitoring patches */
  685.             InstallPatches();
  686.  
  687.             /* if we are to check the memory list periodically,
  688.              * start the timer now
  689.              */
  690.             if(CheckDelay > 0)
  691.                 StartTimer(CheckDelay / 10,(CheckDelay % 10) * (MILLION / 10));
  692.     
  693.             while(TRUE)
  694.             {
  695.                 /* wait for something to happen */
  696.                 signalsReceived = Wait(SIG_Check | SIG_Disable | SIG_Enable | sigWakeup | sigTimer);
  697.  
  698.                 /* received a command? */
  699.                 if(FLAG_IS_SET(signalsReceived,sigWakeup))
  700.                 {
  701.                     APTR parameter = WipeoutSemaphore->ws_Parameter;
  702.                     LONG error = OK;
  703.  
  704.                     /* what are we to do now? */
  705.                     switch(WipeoutSemaphore->ws_Command)
  706.                     {
  707.                         /* update the filter list? */
  708.                         case WIPEOUTCMD_UpdateFilterList:
  709.  
  710.                             if(CANNOT UpdateFilter((STRPTR)parameter))
  711.                                 error = ERROR_NO_FREE_STORE;
  712.  
  713.                             break;
  714.  
  715.                         /* change the check timer delay? */
  716.                         case WIPEOUTCMD_NewCheckDelay:
  717.  
  718.                             CheckDelay = (LONG)parameter;
  719.  
  720.                             /* re-check the check timer delay */
  721.                             signalsReceived |= sigTimer;
  722.                             break;
  723.  
  724.                         /* remunge unallocated memory? */
  725.                         case WIPEOUTCMD_Remunge:
  726.  
  727.                             DPrintf("Remunging memory... ");
  728.                             BeginMemMung();
  729.                             DPrintf("done.\n");
  730.  
  731.                             break;
  732.  
  733.                         /* mark all "current" memory allocations? */
  734.                         case WIPEOUTCMD_Mark:
  735.  
  736.                             DPrintf("Marking memory... ");
  737.                             ChangeMemoryMarks(TRUE);
  738.                             ChangePuddleMarks(TRUE);
  739.                             DPrintf("done.\n");
  740.                             break;
  741.  
  742.                         /* clear all memory marks? */
  743.                         case WIPEOUTCMD_Unmark:
  744.  
  745.                             DPrintf("Clearing memory marks... ");
  746.                             ChangeMemoryMarks(FALSE);
  747.                             ChangePuddleMarks(FALSE);
  748.                             DPrintf("done.\n");
  749.                             break;
  750.  
  751.                         /* show all memory marks? */
  752.                         case WIPEOUTCMD_ShowUnmarked:
  753.  
  754.                             DPrintf("%s\nShowing all unmarked memory allocations\n",Separator);
  755.                             ShowUnmarkedMemory();
  756.                             ShowUnmarkedPools();
  757.                             DPrintf("%s\n\n",Separator);
  758.                             break;
  759.                     }
  760.     
  761.                     /* let the client task go */
  762.                     WipeoutSemaphore->ws_Error = error;
  763.                     Signal(WipeoutSemaphore->ws_Client,SIG_Handshake);
  764.                 }
  765.     
  766.                 /* start or stop the timer, depending on the
  767.                  * check delay length
  768.                  */
  769.                 if(FLAG_IS_SET(signalsReceived,sigTimer))
  770.                 {
  771.                     if(CheckDelay > 0)
  772.                     {
  773.                         StartTimer(CheckDelay / 10,(CheckDelay % 10) * (MILLION / 10));
  774.  
  775.                         signalsReceived |= SIG_Check;
  776.                     }
  777.                     else
  778.                     {
  779.                         StopTimer();
  780.                     }
  781.                 }
  782.  
  783.                 /* check all memory allocations */
  784.                 if(FLAG_IS_SET(signalsReceived,SIG_Check))
  785.                 {
  786.                     struct timeval tv;
  787.  
  788.                     Forbid();
  789.  
  790.                     GetSysTime(&tv);
  791.                     ConvertTimeAndDate(&tv,GlobalDateTimeBuffer);
  792.  
  793.                     DPrintf("%s\nChecking all memory allocations (%s)\n%s\n",
  794.                         Separator,GlobalDateTimeBuffer,Separator);
  795.  
  796.                     CheckAllocatedMemory();
  797.                     CheckPools();
  798.                     CheckFilter();
  799.  
  800.                     DPrintf("%s\n\n",Separator);
  801.  
  802.                     Permit();
  803.                 }
  804.     
  805.                 /* stop monitoring memory allocations */
  806.                 if(FLAG_IS_SET(signalsReceived,SIG_Disable))
  807.                 {
  808.                     if(IsActive)
  809.                     {
  810.                         struct timeval tv;
  811.     
  812.                         Forbid();
  813.     
  814.                         GetSysTime(&tv);
  815.                         ConvertTimeAndDate(&tv,GlobalDateTimeBuffer);
  816.     
  817.                         DPrintf("%s\n%s deactivated (%s)\n%s\n",
  818.                             Separator,ProgramName,GlobalDateTimeBuffer,Separator);
  819.     
  820.                         IsActive = FALSE;
  821.     
  822.                         Permit();
  823.                     }
  824.                 }
  825.     
  826.                 /* restart monitoring memory allocations */
  827.                 if(FLAG_IS_SET(signalsReceived,SIG_Enable))
  828.                 {
  829.                     if(NOT IsActive)
  830.                     {
  831.                         struct timeval tv;
  832.  
  833.                         Forbid();
  834.  
  835.                         GetSysTime(&tv);
  836.                         ConvertTimeAndDate(&tv,GlobalDateTimeBuffer);
  837.  
  838.                         DPrintf("%s\n%s activated (%s)\n%s\n",
  839.                             Separator,ProgramName,GlobalDateTimeBuffer,Separator);
  840.  
  841.                         IsActive = TRUE;
  842.  
  843.                         Permit();
  844.                     }
  845.                 }
  846.             }
  847.         }
  848.     }
  849.  
  850.     /* note that we never arrive here if we are the owner
  851.      * of the wipeout semaphore
  852.      */
  853.     Cleanup();
  854.  
  855.     return(result);
  856. }
  857.